package com.bigdata

import com.alibaba.fastjson
import com.alibaba.fastjson.{JSON, JSONArray}

import scala.io.{BufferedSource, Source}

/**
 * 隐式转换
 */
object Demo28Implicit {

  def main(args: Array[String]): Unit = {
    /**
     * 隐式转换  -- 隐式类型转换  -- 可以动态可以对象增加新的方法
     * 1、隐式转换变量
     * 2、隐式转换方法: 可以隐式将方法的参数类型转换成返回值类型
     * 3、隐式转换类
     * 不能多用，代码的可读性会降低，不知道隐式转换方法里做了什么操作
     */
    // 显示类型转换，把String类型的变量转为int类型
    val str: String = "100"
    // val num: Int = Integer.valueOf(str)
    // val num: Int = str.toInt
    // println(num)

    // 定义一个函数，接收一个int类型的参数，然后数学计算
    def calc(num: Int): Unit = {
      println(num * 2)
    }

    // 需要计算的参数是String类型，不是int
    calc(Integer.valueOf(str))


    /**
     * 定义一个隐式转换方法
     * 可以将参数类型转换成返回值类型
     *
     * 隐式转换的方法和方法名无关,和参数类型返回值类有关
     * 同一个作用域中只能存在一个相同类型的隐式转换
     * 将String 转换成Int的隐式转换的方法
     * 当前作用域中所有的String都可以当成Int类使用
     * 定义一个隐式转换的函数，功能就是把String类型的值转为Int类型
     */
    // 函数名称可以任意定义
    implicit def strToInt(str: String): Int = {
      println("strToInt")
      Integer.valueOf(str)
    }


    // 想要实现一个需求，就是往calc函数中传递一个字符串，做函数的逻辑计算
    // calc("100")
    calc(strToInt(str))

    // 字符串本身有 + 方法，这里调用的是字符串+的逻辑
    println("100" + "20")

    // 字符串没有减法运算，所以这里会先调用隐式转换方法转为int，然后再调用int的减法逻辑做运算
    println("100" - 20)

    // 隐式转换方法定义在其他的类中，需要导入才能生效
    /**
     * 导入class中的隐式转换方法，需要先new出对象，
     * 然后使用import 加上对象.函数名
     *
     * 导入的是object中的隐式转换方法，直接使用import + object名.函数名(_)
     *
     * 函数可以使用_代替，表示导入所有的函数
     */

    // val test = new Test
    //导入隐式转换
    import com.bigdata.Test._

    /**
     * scala的隐式转换很好用，自己写的代码尽量不要用隐式转换，使用隐式转换会让代码的可读性变差，
     * 可以直接调用 隐式转换的参数 的一些不属于这个类的方法， 我们写的代码其实是缺失部分代码逻辑的
     *
     * 如果现在我们引用第三方的jar包，源码无法自己修改，我们想要拓展这些源码的功能
     * 可以添加隐式转换，可以拓展这些类的功能，比如scala的String就比java中的String多了很多丰富的功能
     */
    // json数组
    val jsonStr: String = "data/users.json"
    println(jsonStr.toJSONString)
    // println(Test.strToJsonArray(jsonStr).size())

    println("data/students.txt".getLines().toList)

  }
}


object Test {

  /**
   * 隐式转换
   * 可以将参数类型转换成返回值类型
   */
  implicit def read(path: String): BufferedSource = {
    Source.fromFile(path)
  }

  /**
   * 先要用json的字符串直接调用，JSONArray的方法
   */
  implicit def strToJsonArray(jsonPath: String): JSONArray = {
    val jsonStr: String = Source.fromFile(jsonPath).getLines().toList.mkString("").replace(" ", "")
    JSON.parseArray(jsonStr)
  }
}
